import React, { useEffect, useRef, useState } from 'react'
import { ScrollNavbar, tabsType } from 'rc-scroll-nav-bar'
import { debounce } from 'lib-toolkit'
import { AnchorScrollType, ScrollItemInfo } from '../..'


export default function AnchorScroll(props: AnchorScrollType) {
    // AnchorScroll props
    const {
        initActiveKey = 0,
        children,
        className = '',
        style = {},
        contentStyle = {},
        offsetTop = 0,
        containerId = 'x-anchor-scroll',
        onChange,
        navbarProps,
    } = props
    // ScrollNavbar props
    const { height: tabbarHeight = 40, tabs } = navbarProps
    // 激活索引
    const [activeKey, setActiveKey] = useState<any>(initActiveKey)
    // 是否是点击触发
    const isClick = useRef(false)
    const activeIndex = useRef(0)
    // 滚动盒子
    let scrollBox = useRef<HTMLElement | null>(null)
    // 内容盒子
    let contentBox = useRef<HTMLElement | null>(null)

    // 初始化
    useEffect(() => {
        setActiveKey(initActiveKey)
        // 滚动容器对象
        scrollBox.current = document.querySelector('#' + containerId) as HTMLElement
        // 内容容器对象
        contentBox.current = document.querySelector('#x-anchor-scroll-content') as HTMLElement
        // 容器不存在
        if (!scrollBox.current) {
            scrollBox.current = document.querySelector('#x-anchor-scroll') as HTMLElement
            console.warn(`找不到元素id为“${containerId}”容器`)
        }
        // 滚动盒子距离浏览器顶部的距离
        const offsetTop = scrollBox.current.getBoundingClientRect().top || 0
        scrollBox.current?.setAttribute('style', `overflow: auto;height: calc(100vh - ${offsetTop}px);scroll-behavior: smooth;`)
        if (initActiveKey === 0) return
        onChangeTabs(initActiveKey)
    }, [initActiveKey])

    // 监听滚动
    useEffect(() => {
        if (!scrollBox.current) return
        scrollBox.current?.addEventListener('scroll', onScroll)
        return () => {
            scrollBox.current?.scrollTo(0, 0)
            scrollBox.current?.setAttribute('style', '')
            scrollBox.current?.removeEventListener('scroll', onScroll)
        }
    }, [])

    // 点击跳转到锚点
    const onChangeTabs = (index: number) => {
        index = index > children.length - 1 ? children.length - 1 : index
        onChange && onChange(index)
        activeIndex.current = index
        isClick.current = true
        const anchorElement = document.getElementById('x-anchor-scroll-item-' + index) as HTMLElement
        if (scrollBox.current) {
            // top = 元素距离顶部的距离 - 自定义偏移量 - tabbar高度 - 滚动盒子距离浏览器顶部的距离
            const top = anchorElement.offsetTop - offsetTop - tabbarHeight - scrollBox.current.getBoundingClientRect().top
            scrollBox.current?.scrollTo(0, top)
        }
    }

    // 获取滚动元素位置信息
    const getScrollItemInfo = (tabs: tabsType[] | string[]) => {
        // 用于保存所有元素索引和距离浏览器顶部的距离
        let result: ScrollItemInfo[] = []
        tabs.forEach((item, index) => {
            const element = document.getElementById('x-anchor-scroll-item-' + index)
            result.push({ key: index, top: element?.getBoundingClientRect().top || 0 })
        })
        return result
    }

    // 用于防抖
    let timer: any = null
    // 滚动处理函数
    const scrollFun = (e: any) => {
        let indexList: any[] = []
        window.clearTimeout(timer)
        timer = window.setTimeout(() => {
            // 滚动停止时执行的代码
            isClick.current = false
        }, 66)
        if (isClick.current) return
        // 滚动元素位置信息
        const scrollItemInfo: ScrollItemInfo[] = getScrollItemInfo(tabs)
        for (let index = 0; index < scrollItemInfo.length; index++) {
            const element = scrollItemInfo[index]
            if (Number(contentBox.current?.offsetTop) >= element.top) {
                if (!indexList.includes(element.key)) {
                    indexList.unshift(element.key)
                }
            }
        }
        setActiveKey(indexList[0])
    }

    // 根据滚动定位tab
    const onScroll = debounce(scrollFun, 10)

    return (
        <div id="x-anchor-scroll" className={`x-anchor-scroll ${className}`} style={{ ...style }}>
            <ScrollNavbar {...navbarProps} activeKey={activeKey} onChange={onChangeTabs}></ScrollNavbar>
            <div id="x-anchor-scroll-content" className="x-anchor-scroll-content" style={contentStyle}>
                {
                    // 只渲染符合规格的子组件
                    findChild(children).map((item, index) => {
                        return React.cloneElement(item, { key: index, index: index })
                    })
                }
            </div>
        </div>
    )
}

// 查找子组件
function findChild(children: any[]): any[] {
    let result: any[] = []
    React.Children.forEach(children, (child, index) => {
        if (child?.type?.defaultProps?.name === 'AnchorScrollItem') {
            result.push(child)
        }
    })
    return result
}
